import express from 'express'; // node web应用开发框架
import bodyParser from 'body-parser'; // express中间件，对post请求进行解析
import compression from 'compression'; // node 中间件对请求进行压缩
import morgan from 'morgan'; // node中间件记录日志
import cors from 'cors'; // node 跨域模块
import http from 'http';
import path from 'path'; // node 文件处理模块
import yaml from 'yamljs'; // json 转换插件
import * as api from './api';
import { accessTokenAuth } from './security'; // 验证接口X-Access-Token是否存在

const app = express();
const port = 9530;
const { connector, summarise } = require('swagger-routes-express'); // 使用下面语句改写
// import sre = require('swagger-routes-express') ;

// Compression
app.use(compression());
// Logger
app.use(morgan('dev'));
// Enable CORS
app.use(cors());
// POST, PUT, DELETE body parser
app.use(bodyParser.json({ limit: '20mb' }));
app.use(
  bodyParser.urlencoded({
    limit: '20mb',
    extended: false,
  }),
);
// No cache
app.use((req, res, next) => {
  res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate');
  res.header('Pragma', 'no-cache');
  res.header('Expires', '-1');
  next();
});

// Read and swagger config file
const apiDefinition = yaml.load(path.resolve(__dirname, 'swagger.yml'));
// Create mock functions based on swaggerConfig
const options = {
  security: {
    AccessTokenAuth: accessTokenAuth,
  },
};
const connectSwagger = connector(api, apiDefinition, options);
connectSwagger(app);
// Print swagger router api summary
const apiSummary = summarise(apiDefinition);
console.log(apiSummary);

// Catch 404 error
app.use((req, res, next) => {
  const err = new Error('Not Found');
  res.status(404).json({
    message: err.message,
    error: err,
  });
});

// Create HTTP server.
const server = http.createServer(app);

// Listen on provided port, on all network interfaces.
server.listen(port);
server.on('error', onError);
console.log('Mock server started on port ' + port + '!');

// Event listener for HTTP server "error" event.
function onError(error: any) {
  if (error.syscall !== 'listen') {
    throw error;
  }
  const bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port;
  // handle specific listen errors with friendly messages
  switch (error.code) {
    case 'EACCES':
      console.error(
        'Express ERROR (app) : %s requires elevated privileges',
        bind,
      );
      process.exit(1);
    case 'EADDRINUSE':
      console.error('Express ERROR (app) : %s is already in use', bind);
      process.exit(1);
    default:
      throw error;
  }
}
